/*================================================================
*   Copyright (C) 2019 Guangzhou Firefly Ltd. All rights reserved.
*   
*   文件名称：pm25.c
*   创 建 者：luhuadong
*   创建日期：2019年09月07日
*   描    述：pm2.5传感器驱动 -- GP2Y1014AU
*
================================================================*/


#include "pm25.h"

#define LED_GP2Y_PIN       GET_PIN(C, 7)  /* D9 --> PC7 */
#define ADC_DEV_NAME        "adc1"        /* ADC 设备名称 */
#define ADC_DEV_CHANNEL     1             /* ADC 通道 */

static rt_adc_device_t adc_dev;   /* 定义一个设备，ADC 设备句柄 */ 

int gp2y_hw_init(void)
{
    rt_err_t ret = RT_EOK;

    /* 查找设备。在rt-thread中，你要用一个设备，
       你首先得要去找到它，"adc1"这个名字是系统确定好的
    */
    adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);

    if (adc_dev == RT_NULL){
        rt_kprintf("Can't find %s device!\n", ADC_DEV_NAME);
        return RT_ERROR;
    }
    
    /* 使能设备。找到 adc1 就打开设备和相对应的通道 */
    ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);

    if(ret != RT_EOK) {
        rt_kprintf("Enable %s channel %d failed!\n", ADC_DEV_NAME, ADC_DEV_CHANNEL);
        return ret;
    }
    
    /* 设置 GP2Y 模块 LED 管脚为输出，并初始化为低电平 */
    rt_pin_mode(LED_GP2Y_PIN, PIN_MODE_OUTPUT);
    rt_pin_write(LED_GP2Y_PIN, PIN_LOW);

    return ret;
}

float gp2y_read_pm25(void)
{
    rt_err_t err = RT_EOK;

    int sampling_time = 280;  //等待LED开启的时间是280μs
    int delta_time = 40;      //整个脉冲持续时间为320μs。因此，我们还需再等待40μs

    uint16_t adc_val;
    float dust_val = 0;
    float voltage;

    rt_pin_write(LED_GP2Y_PIN, PIN_HIGH);
    rt_hw_us_delay(sampling_time);
    
    /* 读取采样值 */
    adc_val = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);

    rt_hw_us_delay(delta_time);
    rt_pin_write(LED_GP2Y_PIN, PIN_LOW);

    rt_thread_mdelay(9);
    rt_hw_us_delay(680);  //需要脉宽比0.32ms/10ms的PWM信号驱动传感器中的LED
    
    //voltage = adc_val * 3.3 / 4096;
    voltage = (float)adc_val * 5.0 / 4096;
    dust_val = (5000 * voltage / 29) - (3000 / 29);

    if(dust_val < 0) {
       dust_val = 0; 
    }

    rt_kprintf("ADC value = %d, Voltage = %d.%d, Dust value = %d.%d\n", 
                adc_val, (int)voltage, (int)(voltage * 100) % 100, 
                (int)dust_val, (int)(dust_val * 100) % 100);
    
    
    return dust_val;    
}